﻿// RankingSejmowy 1.0 - Polish parliment statistics for the masses.
// Copyright (C) 2010 Jarosław Dubrownik
//  
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//  
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//  
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
using System;
using RankingSejmowy.BLL.Import.Spider.Analyzers;
using RankingSejmowy.BLL.Import.Spider.Downloaders;
using RankingSejmowy.Model.Import;

namespace RankingSejmowy.BLL.Import.Spider
{
    /// <summary>
    /// Default web implementation of spider.
    /// </summary>
    public class WebSpider : ISpider
    {
        private readonly IPageAnalyzerFactory _pageAnalyzerFactory;
        private readonly ICachedPageDownloader _pageDownloader;

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="pageAnalyzerFactory">PageAnalyzerObject object used to extract links to subpages from page content.</param>
        /// <param name="pageDownloader">PageDownloader object used to download webpage.</param>
        public WebSpider(IPageAnalyzerFactory pageAnalyzerFactory, ICachedPageDownloader pageDownloader)
        {
            _pageAnalyzerFactory = pageAnalyzerFactory;
            _pageDownloader = pageDownloader;
        }

        #region ISpider Members

        public SiteMap GetSiteMap(Uri uri, FetchSetup fetchSetup)
        {
            var siteMap = new SiteMap();
            siteMap.MainPage = new SiteMapPage {Uri = uri};
            GetPage(uri, siteMap.MainPage, fetchSetup);
            return siteMap;
        }

        public DownloadedPage GetSinglePage(Uri uri)
        {
            return _pageDownloader.Download(uri, false);
        }

        public DownloadedPage GetSinglePage(Uri uri, bool disableCache)
        {
            return _pageDownloader.Download(uri, true);
        }

        #endregion

        /// <summary>
        /// Retrives sitemap of passed website address.
        /// </summary>
        /// <param name="uri">Uri of website which should be fetched and analysed.</param>
        /// <returns>Returns SiteMap of specified website.</returns>
        public SiteMap GetSiteMap(Uri uri)
        {
            var siteMap = new SiteMap();
            siteMap.MainPage = new SiteMapPage();
            GetPage(uri, siteMap.MainPage, new FetchSetup {Inceremental = false});
            return siteMap;
        }

        /// <summary>
        /// Recursively called method to get next page down in website hierarchy.
        /// </summary>
        /// <param name="uri">Uri of webpage to download and analyze.</param>
        /// <param name="baseSiteMapPage">Base SiteMapPage for download and analyze.</param>
        private void GetPage(Uri uri, SiteMapPage baseSiteMapPage, FetchSetup fetchSetup)
        {
            baseSiteMapPage.DownloadedPage = _pageDownloader.Download(uri);
            var analyzer = _pageAnalyzerFactory.CreatePageAnalyzer(uri);
            var sitePages = analyzer.AnalyzePage(uri, baseSiteMapPage.DownloadedPage, fetchSetup);
            baseSiteMapPage.SubPages.AddRange(sitePages);
            foreach (var sitePage in sitePages)
            {
                GetPage(sitePage.Uri, sitePage, fetchSetup);
            }
        }
    }
}